4.4 Cookies, and session management

  1. Motivations

    • How to recognize a returning user?
      • Reload this page. What do you see?
      • In TRUQA, when the user comes back later, do you really have to ask the user to enter the username again? What if your application displays the username in 'SignIn' box, which was used right before?
      • Isn't it more user friendly?
      • How to display a greeting message with a specific username, like 'Good morning, Dave!'?
      • When the user leaves TRUQA without 'Sign Out' and he/she comes back, does your application have to ask him/her to sign in again?
    • How to maintain a session?
      • Once the user enters the valid username and password, the TRUQA controller will display the MainPage. The user will send new inputs to the controller. How does the controller know who sent the inputs from the MainPage? What if someone else sends the similar inputs, that is used in the MainPage, without proper SignIn? You should not forget that the server-side programs run only one time, not continually. What if someone accesses the MainPage directly?
      • You may need to leave data in the client side and in the server side too.
      • What do you have to do?

  2. What is an HTTP cookie?
    • Read the three paragraphs in HTTP cookie.
      • What are cookies used for?
      • Where are cookies stored?
      • When are cookies sent? To whom?
      • Is there any security issue?
      • What are thirty-party cookies?
      • Is there any privacy concern?
      • What are authentication cookies?
    • Read the first paragraph in PHP Cookies.
      • Which side sets a cookie?
      • Where is the cookie stored?
      • Which side retrieves the cookie?
      • Are cookies automatically sent?
    • What if the browser is closed? Will the cookies be destroyed?
      • In general, yes, but not all.
      • Those cookies, that are destroyed when the browser is closed, are called session cookies.
      • Session cookies are set with 0 expiration - setcookie($name, $value, 0);
    • Browsers generally accept only 20 cookies from each site and 300 cookies total. In addition, they can limit each cookie to 4 kilobytes. This is why it is not a good idea to use cookies as a data storage.

  3. How to create/destroy a cookie?
    • Read all in PHP Cookies.
      • Which function is used to create a cookie?
      • How to set the expiration time of the cookie? When are cookies destroyed? When the browser is closed?
      • What if the third argument 'expire' is zero? There are two types of cookies.
        • Session cookies with 'expire' of zero - These cookies are destroyed when the browser is closed.
        • Persistent cookies - Destroyed at the set date and time.
      • How to restrict the accessibility to only my application, not to all in the same server computer system?
        • Isn't this important for TRUQA?
        • How to obtain the url name in PHP?
          echo "http://".$_SERVER['HTTP_HOST'].$_SERVER['SCRIPT_NAME'];
          
        • How to obtain the current directory name in PHP?
          echo getcwd();
          
      • Which super global array is used to retrieve cookies?
      • How to modify a cookie value?
      • How to display a welcome message when the user comes back?
      • How to destroy a cookie?
      • How to check if cookies are enabled?
    • Trial 1: Let's try to create a cookie if it is not set. You need to destroy the cookie if it exists after displaying it.

    • It is also possible to use JavaScript Cookies.

  4. How to view cookies stored on Chrome?
    • Settings -> Privacy -> Content settings... -> All cookies and site data...

  5. How to display a welcome message when the user comes back?
    • When the username and password are valid, set the username as a cookie for a certain period of time.
    • In controller.php in TRUQA,
      <?php
      
      /*
      *   When controller.php is accessed for the first time
      */
      
      if (empty($_POST['page'])) {
          $display_modal_window = 'none';
          include ('view_startpage.php');
          exit;
      }
      
      /*
      *   When commands come from StartPage or MainPage
      */
      
      require ('model.php');  // connect to MySQL database; functions to access DB tables
      
      $page = $_POST['page'];
      $command = $_POST['command'];
      
      if ($page == 'StartPage') 
      {
          switch ($command) {
          case 'SignIn':
              $username = ????;
              $password = ????;
              // When the user is valid,
              if (is_valid(???, ???) {  // is_valid() is in model.php
                  ???('username', $username, time() + 24 * 60 * 60);  // Set a cookie for a welcoming message on StartPage for the next visit
                  include('view_mainpage.php');
              }
              // When invalid
              else {
                  $display_modal_window = 'signin';
                  $error_msg_username = '* Wrong username, or';
                  $error_msg_password = '* Wrong password';
                  include('view_startpage.php');
              }
              break;
          ...
          }
      }
      
      else if ($page == 'MainPage') 
      {
          ...
      }
      
      else {
          ...
      }
      ?>
      
    • In view_startpage.php in TRUQA, the cookie value for 'username' is checked and used for the welcome message.
      <div id='welcome-message' style='display:???'></div>
      <script>
          <?php
              if (!empty($_???['username'])) {  // COOKIE super global array
                  echo "document.getElementById('welcome-message').???? = 'Welcome back, " . 
                      $_???['username'] . "!';";
                  echo "document.getElementById('welcome-message').???? = 'block';";
                  
                  // destroy the cookie
                  ???('username', '', ????);
              }
          ?>
      </script>
      

  6. What is a session?
    • Questions:
      • How to check if the commands from MainPage were sent after the user authentication?
      • Does MainPage always need to submit the username?
      • ...
    • Read 'What is a PHP Session' in PHP Sessions.
      • Why is session tracking difficult with HTTP?
      • Where does PHP store the session data? In the client, or in the server?
      • How to distinguish different session data?
      • Is the session id stored in the server or in the client?
      • How to create/obtain the session id?
      • Idea 1: In the MainPage of TRUQA, do you have to keep sending the username and the password whenever any user input is submitted?
        Yes, but inconvenient. Even a third party can send the same username and data.
      • Idea 2: Can you use cookies instead of session data?
        Maybe with some other additional information. But those cookies must be destroyed when the user signs out, or when there is no user activity for a certain period of time.
      • Idea 3: Can you keep session data in the server?
        Yes.

  7. How to use a session with PHP?
    • Read all in PHP Sessions.
      • How to start a session?
      • What does session_start() do? The return value of this function is TRUE or FALSE.
      • How to store/retrieve a session variable?
      • How to destroy a session completely?
    • What data do you think the session in TRUQA should keep?
      Username to access DB for posting questions and so on
    • When do you think the session in TRUQA should be started?
      • Valid SignIn
    • When do you think the session in TRUQA should be destroyed?
      • Sign out - How does the controller know it?
      • Timeout - How does the controller know it? Is it possible that the controller can check any user activity such that mouse movement?
      • When the window is closed - How to know the window is closed?
      • Timer in Controller?
    • Here is an example of controller.php for TRUQA.
      <?php
      
      /*
      *   When controller.php is accessed for the first time
      */
      
      if (empty($_POST['page'])) {
          $display_modal_window = 'none';
          include ('view_startpage.php');
          exit;
      }
      
      /*
      *   When commands come from StartPage or MainPage
      */
      
      require ('model.php');  // connect to MySQL database; functions to access DB tables
      
      $page = $_POST['page'];
      $command = $_POST['command'];
      
      if ($page == 'StartPage') 
      {
          switch ($command) {
          case 'SignIn':
              $username = ???;
              $password = ???;
              // When the user is valid,
              if (is_valid(???, ???) {  // is_valid() is in model.php
                  setcookie('username', $username, time() + 24 * 60 * 60);  // Set a cookie for a welcoming message on StartPage for the next visit
                  session_start();
                  $_SESSION['signedin'] = 'YES';  // session variable - for commands coming from MainPage
                  ????['username'] = $username;  // session variable - for command coming from MainPage
                  include('view_mainpage.php');
              } 
              // When invalid
              else {
                  $display_modal_window = 'signin';
                  $error_msg_username = '* Wrong username, or';
                  $error_msg_password = '* Wrong password';
                  include('view_startpage.php');
              }
              break;
          ...
          }
      }
      
      else if ($page == 'MainPage') 
      {
          session_start();  // in order to access session variables
          
          // What if a user used MainPage without going through the user authentication process?
          if (!isset($_SESSION['signedin'])) {
              $display_modal_window = 'none';
              include ('view_startpage.php');
              exit;
          }
          
          $username = $_SESSION['username'];
      
          switch ($command) {
          case 'SignOut':  // 'SignOut' menu item, or timeout
              session_unset();
              session_destroy();  // It does not unset session variables. session_unset() is needed.
              $display_modal_window = 'none';
              include ('view_startpage.php');
              break;
          case 'SearchQestions':  // It uses $username.
              ...;
              break;
          ...
          }
      }
      
      else {
          ...
      }
      ?>
      
    • In view_mainpage.php in TRUQA, (Note that MainPage might be accessed directly, not through Controller.)
      <?php
      
      // session_start();  // Session is started in controller.php before mainpage.php is included.
      
      if (empty($_SESSION['signedin'])) {
          $display_modal_window = 'none';
          include('view_startpage.php');
          exit;
      }
      ?>
      ...
      
    • Trial 1.5: Let's try to create session values.


  8. How to detect user inactivity? Timeout? How to support automatic SignOut?
    • How to check the user inactivity?
      • Any good idea?
        No typing and no mouse movement for a certain time of period; or when the application window is closed
      • How to implement?
        • Timers - window.setInterval(), window.setTimeout()
        • Events - 'mousemove', 'keydown', 'unload'
        • On window, not document
        • Here is an example of view_mainpage.php.
          <script>
              ...
              var timer = setTimeout(timeout, 10 * 60 * 1000);
              window.addEventListener('mousemove', event_listener_mousemove_or_keydown);  // mousemove on the screen
              window.addEventListener(???, ???);  // for keyboard action
              window.addEventListener('???', function() {  // when the window is closed
                  ????  // ...
              });
              function event_listener_mousemove_or_keydown() {
                  clearTimeout(???);
                  timer = setTimeout(timeout, 10 * 60 * 1000);
              }
              function timeout() {
                  ????  // send the 'SignOut' command to the controller
              }
              ...
          </script>
          
        • Trial 2: Let's try to capture the user inactivity.

    • What to do when there is no user activity?
      • In timeout(), send 'SignOut' to controller.php using an invisible form. In view_mainpage.php,
        <form id='form-signout' method='POST' action='???' ????>  
            <input type='hidden' name='page' value='???'>
            <input type='hidden' name='???' value='SignOut'>
        </form>
        
        <script>
            ...
            function timeout() {
                ...
                document.getElementById('form-signout').???();  // submit the form with the 'SignOut' command
            }
            ...
        </script>
        
      • Trial 3: Let's try to send the 'SignOut' command.


  9. Some review questions and learning outcomes
    • How to create/read/destroy cookies.
    • How to use cookies to display a welcome message.
    • How to use session to share data, e.g., username, over multiple pages.
    • Write the JS code for timeout.
    • When a command comes from MainPage of TRUQA, how to use session to check whether a user signed in.